package net.wanderinghorse.jsonmessage;

import net.wanderinghorse.json.JSONUtil;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * This servlet responds with JavaScript content containing the JSONMessage JavaScript API.
 *
 * TODO: the following POST/GET options:
 *
 * - uncompressed=1: if set, emit minimized/packed forms of the script.
 *
 * - haveJSON: if set to a non-empty, non-0 value then the source for a core JSON object implementation
 * is not emitted. (It is available built-in to many browsers.)
 *

 */
public class JavaScriptServlet extends HttpServlet {
    static final String pathPrefix = "/js/"/*must coincide with path defined in web.xml*/;
    static final List<String> fileList = new ArrayList<String>() {{
        add("json2.js")/*json2 must be first in the list*/;
        add("extendClass.js");
        add("JSONable.inc.js");
        add("JSONMessage.inc.js");
        add("JSONMessage.localconfig.js");
    }};
//    static final List<String> fileListMin = new ArrayList<String>() {{
//        add("json2.min.js")/*json2 must be first in the list*/;
//        add("extendClass.min.js");
//        add("JSONable.min.js");
//        add("JSONMessage.min.js");
//        add("JSONMessage.localconfig.js");
//    }};
    private String cache;
    private boolean useCache = true;

    private void fillCache() throws IOException {
        if( null != cache ) return;
        synchronized(this) {
            if( (null != cache) && !cache.isEmpty() ) return;
            final List<String> list =
                    //isCompressed ? fileListMin : fileList
                    fileList
                    ;
            int count = 0;
            StringBuilder sb = new StringBuilder();
            for( final String fn : list ) {
                final String resource = pathPrefix+fn;
                final InputStream is = getClass().getClassLoader().getResourceAsStream( resource );
                if( null == is ) {
                    throw new IOException("Could not load script resource file ["+resource+"]!");
                }
                sb.append( JSONUtil.readAll(is) );
            }
            cache = sb.toString();
        }

    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        /* TODO: provide an option to cache the generated script. This hinders development,
           however, since it requires a restart of the app server when the JS code changes.
        */
        response.setContentType("text/javascript");
        response.setCharacterEncoding("UTF-8");
        PrintWriter os = response.getWriter();
        if( useCache ) {
            fillCache();
            response.setContentLength( cache.length() );
            os.write( cache );
            return;
        }
//        final String uncompressed = request.getParameter("uncompressed");
//        final boolean isCompressed = ((null==uncompressed)||"0".equals(uncompressed));
        final List<String> list =
                //isCompressed ? fileListMin : fileList
                fileList
                ;
        int count = 0;

        for( final String fn : list ) {
            if( 1 == ++count ) {
                // Provide the client with a way to skip the JSON bits, which are already
                // installed in some browsers.
                final String hasJsonObj = request.getParameter("haveJSON");
                if( (null != hasJsonObj) && !"0".equals(hasJsonObj)) {
                    continue;
                }
            }
            final String resource = pathPrefix+fn;
            final InputStream is =
                 getClass().getClassLoader()
//                JavaScriptServlet.class
//            //Thread.currentThread().getContextClassLoader()
                .getResourceAsStream( resource );
            if( null == is ) {
                throw new IOException("Could not load script resource file ["+resource+"]!");
            }
            os.write(JSONUtil.readAll(is));
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException
    {
        processRequest(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException
    {
        processRequest(request, response);
    }

    @Override
    public void init(final ServletConfig config) throws ServletException {
        super.init(config);
    }
}
